package com.demo.schedule;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.demo.biz.user.model.entity.UserEntity;
import com.demo.biz.user.service.UserService;
import com.github.pagehelper.PageHelper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;

/**
 * @author 曳戈泰尔
 * @version 1.0
 * @description 定时任务 写死执行cron，不可动态修改 执行内容定义
 * @date 2023/3/20 11:32 AM
 */
@Component
@Slf4j
public class ScheduleStaticTask {

    /** 注入用户Service */
    private UserService userService;

    @Autowired
    public void setUserService(UserService userService) {
        this.userService = userService;
    }

    /** 注入 线程池 */
    private Executor threadPoolExecutor;

    @Autowired
    public void setThreadPoolExecutor(Executor threadPoolExecutor) {
        this.threadPoolExecutor = threadPoolExecutor;
    }

    /** 定义分页 开启多线程处理 设置合适的pageSize值 */
    public static Integer pageNum = 1;

    public static Integer pageSize = 10;

    /** 每天凌晨2点定时执行 */
    @Scheduled(cron = "0 0 1 * * ?")
    public void execute() {

        // 处理用户数据
        executeTask();
    }

    /** 执行任务 */
    public void executeTask() {

        // 总数据
        LambdaQueryWrapper<UserEntity> lqwUser = new LambdaQueryWrapper<>();
        lqwUser.eq(UserEntity::getDel, 0);
        Integer total = userService.count(lqwUser);

        // 执行次数
        int count = total / pageSize + 1;

        for (int i = 0; i < count; i++) {

            log.info("定时处理用户数据，正在处理第 {} 页", i);

            executeTaskBatchDealData(pageNum, pageSize);

            /// 处理后的数据影响下一次查询数据，如处理之后的数据会排除在下一次查询数据之外，页码一直1即可，一直获取第一页数据 处理即可；注释pageNum += 1;
            // 处理后的数据不影响下一次查询数据，页码需要递增跟着走，才能查询出所有的数据 进行处理；不注释pageNum += 1;
            // pageNum += 1;
        }
    }

    public void executeTaskBatchDealData(Integer pageNum, Integer pageSize) {

        // 分页查询所有数据
        LambdaQueryWrapper<UserEntity> lqwUser = new LambdaQueryWrapper<>();
        lqwUser.select(UserEntity::getId);
        lqwUser.eq(UserEntity::getDel, 0);

        PageHelper.startPage(pageNum, pageSize);
        List<UserEntity> userEntityList = userService.list(lqwUser);

        if (userEntityList.isEmpty()) {
            return;
        }

        // 线程池处理数据
        // 每一条数据必须被处理，否则需要修改分页算法，不然处理数据会不完整
        CountDownLatch countDownLatch = new CountDownLatch(userEntityList.size());
        userEntityList.forEach(
                item -> {
                    threadPoolExecutor.execute(
                            new Runnable() {
                                @Override
                                public void run() {

                                    item.setDel(1);
                                    item.setUpdateTime(LocalDateTime.now());

                                    countDownLatch.countDown();
                                }
                            });
                });

        try {
            countDownLatch.await();
        } catch (Exception ex) {
            log.error("定时处理用户数据，处理第 {} 页失败，原因：{}", pageNum, ex.getMessage());
        }

        if (!userService.updateBatchById(userEntityList)) {
            log.error("批量更新数据库失败，User ID-1：{}", userEntityList.get(0).getId());
        }
    }
}
